package com.idsmanager.zdh.service.impl;


import com.idsmanager.commons.utils.paginated.PaginatedLoader;
import com.idsmanager.oauth.domain.security.IdsUserDetails;
import com.idsmanager.oauth.domain.security.SecurityUtils;
import com.idsmanager.oauth.domain.security.User;
import com.idsmanager.oauth.domain.security.UserRepository;
import com.idsmanager.zdh.service.UserService;
import com.idsmanager.oauth.service.dto.user.*;
import com.idsmanager.zdh.service.business.*;
import com.idsmanager.zdh.service.business.api.RestDelUserByGuidRemover;
import com.idsmanager.zdh.service.business.api.RestFindUserByUsernameLoader;
import com.idsmanager.zdh.service.business.api.RestUserUpdater;
import com.idsmanager.zdh.service.business.portal.*;
import com.idsmanager.zdh.service.business.api.RestCreateUserHandler;
import com.idsmanager.zdh.service.dto.api.UserApiResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

@Service("userService")
public class UserServiceImpl implements UserService, UserDetailsService {


    private static final Logger LOG = LoggerFactory.getLogger(UserServiceImpl.class);

    @Autowired
    private UserRepository userRepository;

    @Override
    public boolean isExistedUsername(String username) {
        final User user = userRepository.findByUsername(username);
        return user != null;
    }

    @Override
    public UserApiResult findByUsername(String username) {
        RestFindUserByUsernameLoader loader = new RestFindUserByUsernameLoader();
        return loader.load(username);
    }

    @Override
    public UserApiResult delUserByGuid(String uuid) {
        RestDelUserByGuidRemover handler = new RestDelUserByGuidRemover();
        return handler.remove(uuid);
    }

    @Override
    public UserApiResult restUpdateUser(UserEditTableDto userTableDto) {
        RestUserUpdater updater = new RestUserUpdater(userTableDto);
        return updater.update();
    }

    @Override
    public UserPaginated loadUserPaginated(UserPaginated paginated) {
        final Map<String, Object> map = paginated.queryMap();
        return paginated.load(new PaginatedLoader<UserDto>() {
            @Override
            public List<UserDto> loadList() {
                final List<User> list = userRepository.findUserPaginated(map);
                return UserDto.toDtos(list);
            }

            @Override
            public long loadTotalSize() {
                return userRepository.totalUserPaginated(map);
            }
        });
    }

    @Override
    public String createUser(UserFormDto formDto) {
        CreateUserHandler handler = new CreateUserHandler(formDto);
        return handler.handle();
    }

    @Override
    public void archiveUserByGuid(String guid) {
        final User user = userRepository.findByGuid(guid);

        LOG.debug("{}|Delete User: {}", SecurityUtils.username(), user);
        userRepository.removeUser(user);
    }

    @Override
    public void updateMySetting(MySettingDto formDto) {
        MySettingDtoUpdater updater = new MySettingDtoUpdater(formDto);
        updater.update();
    }


    @Override
    public String initialDefaultUser() {
        DefaultUserInitializer initializer = new DefaultUserInitializer();
        return initializer.initial();
    }

    public String createUser(UserTableDto userTableDto) {
        CreateUserTableHandler handler = new CreateUserTableHandler(userTableDto);
        return handler.handle();
    }

    @Override
    public UserApiResult createUser(UserRestTableDto userRestTableDto) {
        RestCreateUserHandler handler = new RestCreateUserHandler(userRestTableDto);
        return handler.handle();
    }

    @Override
    public UserEditTableDto findByGuid(String uuid) {
        User user = userRepository.findByGuid(uuid);
        return new UserEditTableDto(user);
    }

    @Override
    public String updateUser(UserEditTableDto userTableDto) {

        UserTableDtoUpdater updater = new UserTableDtoUpdater(userTableDto);
        return updater.update();
    }

    @Override
    public UserTableDto resetpassword(String uuid) {
        ResetUserPasswordHandler handler = new ResetUserPasswordHandler(uuid);
        return handler.handle();
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException("Not found by username: " + username);
        }
        return new IdsUserDetails(user);
    }
}
